6.3 select

select一般是与goroutinechannel一起使用的。

它的主要作用是用来从多个channel中读取数据。

相当于使用一个goroutine通过select来读取多个channel的数据。

如果所有channel都没有数据,那么就会阻塞,直到其中一个channel有数据为止。

如果多个channel都有数据,那么就会随机从其中一个先读取数据。

本节代码存放目录为 lesson18

select使用

在上一节中我们已经讲到了channel,接下来我们将演示select如何使用。代码如下所示:

func main() {
    var (
        wg               sync.WaitGroup
        numberChan       chan int
        numberBufferChan chan int
    )
    numberChan = make(chan int)
    numberBufferChan = make(chan int, 5)

    wg.Add(1)
    go func() {
        defer wg.Done()
        for i := 0; i < 10; i++ {
            fmt.Printf("写入数据: %d\n", i)
            numberChan <- i
            time.Sleep(time.Duration(1) * time.Second)
        }
        close(numberChan)
    }()

    wg.Add(1)
    go func() {
        defer wg.Done()
        for i := 100; i < 110; i++ {
            fmt.Printf("写入数据Buffer: %d\n", i)
            numberBufferChan <- i
            time.Sleep(time.Duration(1) * time.Second)
        }
        close(numberBufferChan)
    }()

    wg.Add(1)
    go func() {
        defer wg.Done()
        for {
            select {
            case number1, ok := <-numberChan:
                if !ok {
                    numberChan = nil
                } else {
                    fmt.Printf("读取数据: %d\n", number1)
                }
            case number2, ok := <-numberBufferChan:
                if !ok {
                    numberBufferChan = nil
                } else {
                    fmt.Printf("读取数据Buffer: %d\n", number2)
                }
            }
            if numberChan == nil && numberBufferChan == nil {
                break
            }
        }
    }()

    wg.Wait()
}

在上面的代码中,我们创建了两个通道,通过两个协程进行通道数据的发送。

之后我们开启了另一个协程,通过select读取两个通道的数据。

上面的例子演示了select的常用操作,另外的用法就是我们在学习goroutine时所使用到的select{}

其实select{}也是利用了自身的这一特点,从而让主线程一直阻塞,直到所有的协程都执行完毕。

小结

select在日常场景中使用不算多,不过在一些复杂的业务场景中,比如支付场景,使用的还是比较多的。

本节总结如下:

  • select用于同时读取多个通道的数据

  • 用法与switch类似,但是不能在case里面使用break,否则整个协程都会退出

  • 通道没有数据时会进行阻塞,这时候如果定义了default,就会执行default里面的代码

  • 多个通道都有数据时,程序会基于公平性的原则,随机选择一个读取

results matching ""

    No results matching ""